﻿using System;
using System.Collections.Generic;
using System.Text;
using AAA.Meta.Quote.Data;

namespace AAA.Meta.Chart.Data
{
    public class ProfilePeriod
    {
        private DateTime _startTime;
        private int _iTimePeriod = 15 * 60;
        private float _fPriceInterval;
        private float _fPeriodHighest;
        private float _fPeriodLowest;
        private float _fPeriodOpen;
        private float _fPeriodClose;
        private Dictionary<float, List<int>> _dicVolumeProfile;
        private Dictionary<float, List<int>> _dicTickProfile;
        private List<float> _lstPrice;
        private float _fLastPrice;

        public ProfilePeriod()
        {
            _startTime = DateTime.Parse(DateTime.Now.ToString("yyyy/MM/dd") + " 08:45:01");
            _fPeriodHighest = -float.MaxValue;
            _fPeriodLowest = float.MaxValue;
            _fPeriodClose = float.NaN;
            _fPeriodOpen = float.NaN;
            _dicVolumeProfile = new Dictionary<float, List<int>>();
            _dicTickProfile = new Dictionary<float, List<int>>();
            _lstPrice = new List<float>();
        }

        public float PeriodHighest
        {
            get { return _fPeriodHighest; }
        }

        public float PeriodLowest
        {
            get { return _fPeriodLowest; }
        }

        public float PeriodOpen
        {
            get { return _fPeriodOpen; }
        }

        public float PeriodClose
        {
            get { return _fPeriodClose; }
        }

        public int PeriodVolume
        {
            get
            {       int _iPeriodVolume = 0;
                    foreach (float flPrice in _dicVolumeProfile.Keys)
                    {
                        foreach(int intVolume in _dicVolumeProfile[flPrice]) {
                            _iPeriodVolume = _iPeriodVolume + intVolume;
                        }
                    }
                    return _iPeriodVolume; }
        }

        public int PeriodTicks
        {
            get
            {
                int _iPeriodTicks = 0;
                foreach (float flPrice in _dicTickProfile.Keys)
                {
                    foreach (int intTick in _dicTickProfile[flPrice])
                    {
                        _iPeriodTicks = _iPeriodTicks + intTick;
                    }
                } 
                return _iPeriodTicks;
            }
        }

        public int TPOCount
        {
            get 
            {
                return _lstPrice.Count;
            }
        }

        public DateTime StartTime
        {
            get { return _startTime; }
            set { _startTime = value; }
        }

        public DateTime EndTime
        {
            get {   return StartTime.AddSeconds(TimePeriod-1);}
        }

        public float PriceInterval
        {
            get { return _fPriceInterval; }
            set { _fPriceInterval = value; }
        }

        public int TimePeriod
        {
            get { return _iTimePeriod; }
            set { _iTimePeriod = value; }
        }

        public List<float> PriceList
        {
            get { return _lstPrice; }
        }

        public float VolumeAtPrice(float fPrice)
        {
            return _dicVolumeProfile.ContainsKey(fPrice)
                    ? _dicVolumeProfile[fPrice][0]
                    : 0;
        }

        public int TickAtPrice(float fPrice)
        {
            return _dicTickProfile.ContainsKey(fPrice)
                    ? _dicTickProfile[fPrice][0]
                    : 0;
        }

        public float PriceLabel(float fPrice)
        {
            return Util.ProfileUtil.CalPriceLabel(PriceInterval, fPrice);
            //return (float)(Math.Floor(fPrice / PriceInterval) * PriceInterval);
        }
        
        public float LastPrice
        {
            get { return _fLastPrice; }
        }

        public void AddData(DateTime dtTime, float fPrice, int iVolume)
        {
            AddData(dtTime, fPrice, iVolume, 1);
        }

        public void AddData(DateTime dtTime, float fPrice, int iVolume, int iTick)
        {
            List<int> lstVol;
            float fPriceLabel;

            try
            {
                _fPeriodHighest = Math.Max(fPrice, PeriodHighest);
                _fPeriodLowest = Math.Min(fPrice, PeriodLowest);

                fPriceLabel = PriceLabel(fPrice);

                if (_lstPrice.IndexOf(fPriceLabel) < 0)
                {
                    _lstPrice.Add(fPriceLabel);
                    _dicVolumeProfile.Add(fPriceLabel, new List<int>());
                    _dicTickProfile.Add(fPriceLabel, new List<int>());
                    _lstPrice.Sort();
                }

                lstVol = _dicVolumeProfile[fPriceLabel];
                if (lstVol.Count == 0)
                    lstVol.Add(0);
                lstVol[0] += iVolume;

                lstVol = _dicTickProfile[fPriceLabel];
                if (lstVol.Count == 0)
                    lstVol.Add(0);
                lstVol[0] += iTick;
                if (float.IsNaN(_fPeriodOpen)) {
                    _fPeriodOpen = fPrice;
                }
                _fPeriodClose = fPrice;
                _fLastPrice = fPrice;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message + "," + ex.StackTrace);
            }
        }

        public void UpdateOpenClosePrice(List<BarRecord> lstBarRecord)
        {
            bool blFisrt = true;
             foreach (BarRecord barRecord in lstBarRecord) {
                 //if (barRecord.BarDateTime.ToString("yyyy/MM/dd HH:mm") == StartTime.ToString("yyyy/MM/dd HH:mm"))
                 if (blFisrt)
                 {
                     _fPeriodOpen = barRecord.V0;
                     blFisrt = false;
                 }
                 if (barRecord.BarDateTime.ToString("yyyy/MM/dd HH:mm") == EndTime.ToString("yyyy/MM/dd HH:mm"))
                 {
                     _fPeriodClose = barRecord.V3;
                     _fLastPrice = _fPeriodClose;
                 }
             }
        } 
    }
}
